﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Configuration;
using App.Core.Service.Vendor;
using App.Core.Entities.Identity;
using App.Core.Service.Identity;
using App.Core.Infrastructure;
using App.Core.Infrastructure.Extensions;
using App.Dto.Dtos.Vendor;
using App.Dto.Dtos.Identity;
using AutoMapper;

namespace App.Web.Controllers
{
    [System.Web.Http.Authorize]
    [System.Web.Http.RoutePrefix("api/System")]
    public class SystemController : ApiController
    {
        readonly IMenuService iMenuService;
        readonly IRoleService iRoleService;
        readonly IUserRoleService iUserRoleService;
        readonly IUserService iUserService;
        readonly IModuleService iModuleService;

        public SystemController(IMenuService menuService,
            IRoleService roleService,
            IUserRoleService userRoleService,
            IUserService userService,
            IModuleService moduleService)
        {
            this.iMenuService = menuService;
            this.iRoleService = roleService;
            this.iUserRoleService = userRoleService;
            this.iUserService = userService;
            this.iModuleService = moduleService;
        }

        #region Menu
        [ActionName("GetMenu")]
        [HttpGet]
        public async Task<IHttpActionResult> GetMenu(int id)
        {
            MenuEntity entity = await this.iMenuService.FirstOrDefaultAsync(x => x.Id == id);
            
            var vmodel = new MenuDto();
            Mapper.Map(entity, vmodel); 

            return Ok(new { IsAccess = true, Model = vmodel });
        }

        [ActionName("GetMenuList")]
        [HttpGet]
        public async Task<IHttpActionResult> GetMenuList(string title = "",int parentId= 0, int pageIndex = 1, int pageSize = 10)
        {
            Expression<Func<MenuEntity, bool>> condition = x => x.ParentId == parentId 
            && (String.IsNullOrEmpty(title) || x.Title.Contains(title));
            Expression<Func<MenuEntity, int>> orderBy = x => x.SortNo;

            int total = await this.iMenuService.CountAsync(condition);
            List<MenuEntity> entities = await this.iMenuService.GetByPagerAsync<int>(condition, orderBy, pageIndex, pageSize, isOrderByAsc:true);

            IList<MenuDto> vmodel = new List<MenuDto>(); 
            Mapper.Map(entities, vmodel); 

            return Ok(new { total = total, pageindex = pageIndex, pagesize = pageSize, list = vmodel }); 
        }

        [ActionName("MenuDelete")]
        [HttpGet]
        public async Task<IHttpActionResult> MenuDelete(int Id)
        {
            MenuEntity entity = await this.iMenuService.FirstOrDefaultAsync(x => x.Id == Id);
            if (entity != null)
            {
                await this.iMenuService.DeleteAsync(entity);
            }
            return Ok(new { IsAccess = true });
        }

        [ActionName("MenuEdit")]
        [HttpPost]
        public IHttpActionResult MenuEdit([FromBody]MenuDto vmodel)
        {
            if (!ModelState.IsValid)
            {
                return Ok(new { IsAccess = false, Tag = "FormFeildIncomplete" });
            }

            if (vmodel.Id > 0)
            {
                var entity = this.iMenuService.FirstOrDefault(x => x.Id == vmodel.Id);
                Mapper.Map(vmodel, entity);
                this.iMenuService.Update(entity);
            }
            else
            {
                var entity = new MenuEntity();
                Mapper.Map(vmodel, entity);
                this.iMenuService.Add(entity);
            }

            return Ok(new { IsAccess = true });
        }
        #endregion

        #region Role

        [ActionName("GetRoleList")]
        [HttpGet]
        public async Task<IHttpActionResult> GetRoleList(string name = "", int parentId = 0, int pageIndex = 1, int pageSize = 10)
        {
            Expression<Func<RoleEntity, bool>> condition = x => (String.IsNullOrEmpty(name) || x.Name.Contains(name));
            Expression<Func<RoleEntity, int>> orderBy = x => x.Id;

            int total = await this.iRoleService.CountAsync(condition);
            List<RoleEntity> entities = await this.iRoleService.GetByPagerAsync<int>(condition, orderBy, pageIndex, pageSize, true);

            IList<RoleDto> vmodel = new List<RoleDto>();
            Mapper.Map(entities, vmodel);

            return Ok(new { total = total, pageindex = pageIndex, pagesize = pageSize, list = vmodel });
        }

        [ActionName("GetRole")]
        [HttpGet]
        public async Task<IHttpActionResult> GetRole(int id)
        {
            RoleEntity entity = await this.iRoleService.FirstOrDefaultAsync(x => x.Id == id);
            
            var vmodel = new RoleDto();
            Mapper.Map(entity, vmodel);

            return Ok(new { IsAccess = true, Model = vmodel });
        }

        [ActionName("RoleEdit")]
        [HttpPost]
        public IHttpActionResult RoleEdit([FromBody]RoleDto vmodel)
        {
            if (!ModelState.IsValid)
            {
                return Ok(new { IsAccess = false, Tag = "FormFeildIncomplete" });
            }

            if (vmodel.Id > 0)
            {
                RoleEntity entity = this.iRoleService.FirstOrDefault(x => x.Id == vmodel.Id);
                Mapper.Map(vmodel, entity);
                this.iRoleService.Update(entity);
            }
            else
            {
                var entity = new RoleEntity();
                Mapper.Map(vmodel, entity);
                this.iRoleService.Add(entity);
            }

            return Ok(new { IsAccess = true });
        }

        [ActionName("RoleDelete")]
        [HttpGet]
        public async Task<IHttpActionResult> RoleDelete(int Id)
        {
            RoleEntity entity = await this.iRoleService.FirstOrDefaultAsync(x => x.Id == Id);
            if (entity != null)
            {
                await this.iRoleService.DeleteAsync(entity);
            }
            return Ok(new { IsAccess = true });
        }

        [ActionName("GetRoleUserList")]
        [HttpGet]
        public async Task<IHttpActionResult> GetRoleUserList(int id, int parentId = 0, int pageIndex = 1, int pageSize = 10)
        {
            Expression<Func<UserRoleEntity, bool>> condition = x => x.RoleId == id;
            Expression<Func<UserRoleEntity, int>> orderBy = x => x.UserId;

            int total = await this.iUserRoleService.CountAsync(condition);
            List<UserRoleEntity> entities = await this.iUserRoleService.GetByPagerAsync<int>(condition, orderBy, pageIndex, pageSize, true);

            var userEntities = new List<UserEntity>();
            if (entities != null && entities.Count > 0)
            {
                int[] userIdArr = entities.Select(x => x.UserId).ToArray();
                userEntities = await this.iUserService.GetAllAsync(x => userIdArr.Contains(x.Id));
            }
            

            IList<UserDto> vmodel = new List<UserDto>();
            Mapper.Map(userEntities, vmodel);

            return Ok(new { isAccess = true,total = total, pageindex = pageIndex, pagesize = pageSize, list = vmodel });
        }
         
        [ActionName("AddRoleUser")]
        [HttpGet]
        public async Task<IHttpActionResult> AddRoleUser(int id = 0,string userId = "")
        {
            Expression<Func<UserRoleEntity, bool>> condition = x => x.RoleId == id; 
            List<UserRoleEntity> entities = await this.iUserRoleService.GetAllAsync(condition);
            int[] userIdArr = userId.Split(',').Where(x => !String.IsNullOrEmpty(x)).Select(x => Int32.Parse(x)).Where(x => !entities.Any(y => y.UserId == x)).ToArray();

            if (userIdArr != null && userIdArr.Length > 0)
            {
                foreach (var item in userIdArr)
                {
                    var userRole = new UserRoleEntity();
                    userRole.RoleId = id;
                    userRole.UserId = item;
                    this.iUserRoleService.Add(userRole);
                }
            }

            return Ok(new { IsAccess = true });
        }

        [ActionName("RemoveRoleUser")]
        [HttpGet]
        public async Task<IHttpActionResult> RemoveRoleUser(int id = 0, int userId = 0)
        {
            Expression<Func<UserRoleEntity, bool>> condition = x => x.RoleId == id && x.UserId == userId;
            List<UserRoleEntity> entities = await this.iUserRoleService.GetAllAsync(condition);

            foreach (var item in entities)
            {
                this.iUserRoleService.Delete(item);
            }

            return Ok(new { IsAccess = true });
        }

        [ActionName("GetRolePermission")]
        [HttpGet]
        public async Task<IHttpActionResult> GetRolePermission(int id)
        {
            List<ModuleEntity> moduleEntities = await this.iModuleService.GetAllAsync();
            RoleEntity roleEntity = await this.iRoleService.FirstOrDefaultAsync(x => x.Id == id);

            //当前角色已经选中的权限集合
            IDictionary<string, string> roleModulePermission = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            if (!String.IsNullOrEmpty(roleEntity.ModulePermissions))
            {
                //拥有的模块权限集合，结构：Mudule=权限1,权限2
                string[] moduleAndPermissions = roleEntity.ModulePermissions.Split(';');
                foreach (var item in moduleAndPermissions)
                {
                    if (String.IsNullOrEmpty(item))
                        continue;

                    //把模块和权限分开
                    string[] moduleAndPermission = item.Split('=');
                    string module = moduleAndPermission.First();
                    string permissions = moduleAndPermission.Length > 1 ? moduleAndPermission[1] : String.Empty;
                    if (String.IsNullOrEmpty(module))
                        continue;
                    if (!roleModulePermission.ContainsKey(module))
                    {
                        roleModulePermission.Add(module, permissions);
                    }
                    else {
                        roleModulePermission[module] = String.Concat(roleModulePermission[module],",",permissions);
                    }
                }
            }
            IList<ModulePermissionDto> modulePermissionVm = new List<ModulePermissionDto>();
            foreach (var moduleEntity in moduleEntities)
            {
                IDictionary<string, bool> modulePermission = new Dictionary<string, bool>();
                string permissionSelected = roleModulePermission.ContainsKey(moduleEntity.Module) ? roleModulePermission[moduleEntity.Module] : String.Empty;
                string[] permissionSelectedSplit = permissionSelected.Split(',');

                if (!String.IsNullOrEmpty(moduleEntity.Permissions))
                {
                    string[] permissions = moduleEntity.Permissions.Split(',');
                    foreach (var permission in permissions)
                    {
                        bool isSelected = permissionSelectedSplit.Any(x => x.Equals(permission,StringComparison.OrdinalIgnoreCase));

                        if (!modulePermission.ContainsKey(permission))
                        {
                            modulePermission.Add(permission, isSelected);
                        }
                        else {
                            isSelected = isSelected || modulePermission[permission];
                            modulePermission[permission] = isSelected;
                        } 
                    }
                }

                IList<PermissionDto> permissionVm = modulePermission.Select(x => new PermissionDto() { Permission = x.Key, IsSelected = x.Value }).ToList(); 
                modulePermissionVm.Add(new ModulePermissionDto() { Module = moduleEntity.Module, Permissions = permissionVm });
            }

            return Ok(new { IsAccess = true,ModulePermissions = modulePermissionVm});
        }

        [ActionName("EditRolePermission")]
        [HttpPost]
        public async Task<IHttpActionResult> EditRolePermission([FromBody]RoleDto vm)
        {
            RoleEntity roleEntity = await this.iRoleService.FirstOrDefaultAsync(x => x.Id == vm.Id);
            roleEntity.ModulePermissions = vm.ModulePermissions;
            this.iRoleService.Update(roleEntity);
            return Ok(new { IsAccess = true });
        }

        #endregion

        #region User

        [ActionName("GetUserList")]
        [HttpGet]
        public async Task<IHttpActionResult> GetUserList(string userName = "", int parentId = 0, int pageIndex = 1, int pageSize = 10)
        {
            Expression<Func<UserEntity, bool>> condition = x => (String.IsNullOrEmpty(userName))|| x.UserName.Contains(userName);
            Expression<Func<UserEntity, int>> orderBy = x => x.Id;

            int total = await this.iUserService.CountAsync(condition);
            List<UserEntity> entities = await this.iUserService.GetByPagerAsync<int>(condition, orderBy, pageIndex, pageSize, true);
              

            IList<UserDto> vmodel = new List<UserDto>();
            Mapper.Map(entities, vmodel);

            return Ok(new { isAccess = true,total = total, pageindex = pageIndex, pagesize = pageSize, list = vmodel });
        }


        [ActionName("GetUser")]
        [HttpGet]
        public async Task<IHttpActionResult> GetUser(int id)
        {
            Expression<Func<UserEntity, bool>> condition = x => x.Id == id;
            UserEntity entity = await this.iUserService.FirstOrDefaultAsync(condition);
            UserDto vmodel = new UserDto();
            Mapper.Map(entity, vmodel);
            return Ok(new { isAccess = true,Model = vmodel });
        }

        [ActionName("UserEdit")]
        [HttpPost]
        public async Task<IHttpActionResult> UserEdit([FromBody]UserDto vmodel)
        {
            if (!ModelState.IsValid)
            {
                return Ok(new { IsAccess = false, Tag = "FormFeildIncomplete" });
            }

            if (vmodel.Id > 0)
            {
                var entity = this.iUserService.FirstOrDefault(x => x.Id == vmodel.Id);
                entity.Email = vmodel.Email;
                entity.PhoneNumber = vmodel.PhoneNumber;
                this.iUserService.Update(entity);
            }
            else
            {
                var entity = new UserEntity();
                Mapper.Map(vmodel, entity);
                this.iUserService.Add(entity);
            }

            return Ok(new { IsAccess = true });
        }
        #endregion

        #region Module

        [ActionName("GetModuleList")]
        [HttpGet]
        public async Task<IHttpActionResult> GetModuleList(string module = "")
        {
            Expression<Func<ModuleEntity, bool>> condition = x => (String.IsNullOrEmpty(module)) || x.Module.Contains(module);
            Expression<Func<ModuleEntity, int>> orderBy = x => x.Id;

            int total = await this.iModuleService.CountAsync(condition);
            List<ModuleEntity> entities = await this.iModuleService.GetAllAsync(condition);


            IList<ModuleDto> vmodel = new List<ModuleDto>();
            Mapper.Map(entities, vmodel);

            return Ok(new { isAccess = true, list = vmodel });
        }

        [ActionName("GetModule")]
        [HttpGet]
        public async Task<IHttpActionResult> GetModule(int id)
        {
            ModuleEntity entity = await this.iModuleService.FirstOrDefaultAsync(x => x.Id == id);

            var vmodel = new ModuleDto();
            Mapper.Map(entity, vmodel);

            return Ok(new { IsAccess = true, Model = vmodel });
        }

        [ActionName("ModuleEdit")]
        [HttpPost]
        public IHttpActionResult ModuleEdit([FromBody]ModuleDto vmodel)
        {
            if (!ModelState.IsValid)
            {
                return Ok(new { IsAccess = false, Tag = "FormFeildIncomplete" });
            }

            if (vmodel.Id > 0)
            {
                var entity = this.iModuleService.FirstOrDefault(x => x.Id == vmodel.Id);
                Mapper.Map(vmodel, entity);
                this.iModuleService.Update(entity);
            }
            else
            {
                var entity = new ModuleEntity();
                Mapper.Map(vmodel, entity);
                this.iModuleService.Add(entity);
            }

            return Ok(new { IsAccess = true });
        }

        [ActionName("ModuleDelete")]
        [HttpGet]
        public async Task<IHttpActionResult> ModuleDelete(int id)
        {
            ModuleEntity entity = await this.iModuleService.FirstOrDefaultAsync(x => x.Id == id);
            if (entity != null)
            {
                await this.iModuleService.DeleteAsync(entity);
            }
            return Ok(new { IsAccess = true });
        }

        #endregion
    }
}
